import { BadRequestException, Injectable } from '@nestjs/common'
import { RegisterDto } from './dto/register.dto'
import { MailService } from '../../internal-modules/mail/mail.service'
import { VerificationCode } from '../../internal-modules/mail/mail.interface'
import { InjectRepository } from '@nestjs/typeorm'
import { Repository } from 'typeorm'
import { User } from '../../../database/entities/user.entity'
import * as bcrypt from 'bcrypt'
import { validateEmail } from '../../../common/utils'

@Injectable()
export class RegisterService {
  // 存储发送的验证码
  private verificationCodes: Map<string, VerificationCode> = new Map()

  constructor(
    private readonly mailService: MailService,
    @InjectRepository(User)
    private readonly userRepository: Repository<User>
  ) {}

  // 发送验证码
  async sendVerificationCode(email: string): Promise<void> {
    validateEmail(email)

    // 检查邮箱是否已注册
    const existingUser = await this.userRepository.findOne({ where: { email } })
    if (existingUser) {
      throw new BadRequestException('用户已存在')
    }

    const codeInfo = this.mailService.generateVerificationCode()
    this.verificationCodes.set(email, codeInfo)

    // 发送验证码邮件
    await this.mailService.sendVerificationCode(email, codeInfo.code)
  }

  // 验证并注册
  async verifyAndRegister(registerDto: RegisterDto): Promise<User> {
    const verificationData = this.verificationCodes.get(registerDto.email)
    if (!verificationData) {
      throw new BadRequestException('请先获取验证码')
    }

    if (verificationData.code !== registerDto.code) {
      throw new BadRequestException('验证码不正确')
    }

    if (new Date().valueOf() > verificationData.expiresAt) {
      this.verificationCodes.delete(registerDto.email)
      throw new BadRequestException('验证码已过期，请重新获取')
    }

    // 检查邮箱是否已注册（二次检查）
    const existingUser = await this.userRepository.findOne({
      where: { email: registerDto.email }
    })
    if (existingUser) {
      throw new BadRequestException('用户已存在')
    }

    // 密码加密
    const salt = await bcrypt.genSalt()
    const hashedPassword = await bcrypt.hash(registerDto.password, salt)

    // 创建新用户
    const user = new User()
    user.email = registerDto.email
    user.nickname = registerDto.nickname
    user.password = hashedPassword
    user.createdAt = new Date()

    // 清除验证码
    this.verificationCodes.delete(registerDto.email)

    // 保存用户
    return this.userRepository.save(user)
  }
}
